import json
import time
import requests
import traceback
import threadpool
from common import constants

from datetime import datetime
from dialogue.cache.cache_dialogue import global_dialogue_data, global_dialogue_llm
from dialogue.service.dialogue_storage import dialogueStorage
from dialogue.util.data_handling import dataHandlingUtil
from dialogue.util.date_transmission import send_data_by_redis, send_data_by_es
from settings import log
from utils.database_utils import get_case_info_by_session_id

dataHandling = dataHandlingUtil()
pool = threadpool.ThreadPool(15)


def return_error():
    return {"reply": "对不起，由于系统或网络问题，本次业务无法正常进行，请稍后重新联系。"}


class dialogueService(object):

    def __init__(self):
        pass

    async def start(self, session_id, workspace_id, dialogue_id, user_id):
        query_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        request_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
        result = return_error()
        if workspace_id is None or dialogue_id is None or len(global_dialogue_data) < 1:
            log.info("[start]参数为空 session_id:{},workspace_id:{}, dialogue_id:{},user_id:{}"
                     .format(session_id, workspace_id, dialogue_id, user_id))
            return result
        dialogue_conf = global_dialogue_data.get(dialogue_id)
        if dialogue_conf is None:
            return result
        dialogueSession, result = dataHandling.data_dialogue_session_start(session_id, workspace_id, dialogue_id,
                                                                           result, dialogue_conf)

        user_info = get_case_info_by_session_id(session_id)
        base_info = dataHandling.data_handling_user_info(user_info, session_id)
        dialogueSession["baseInfo"] = base_info
        if user_info is not None:
            dialogueSession["userInfo"] = user_info
        conversation_history = []
        start_time = datetime.now()
        # 3.调用大模型
        llm_data = await self.get_llm_data(dialogue_id, conversation_history, session_id, base_info,
                                           dialogueSession.get('model_name'))
        result_msg, id_result_json = dataHandling.data_handling_result(llm_data, base_info, True)
        if result_msg:
            result_msg = '[{}]《silence_time:3000ms》{}'.format(dialogueSession.get('bot_name', ''),
                                                              result_msg)
        result["reply"] = result_msg

        conversation_history = dataHandling.data_handling_msg_data(conversation_history, llm_data,
                                                                   constants.ROLE_ASSISTANT, query_time)
        dialogueSession["conversation_history"] = conversation_history

        dialogueSession = dataHandling.update_session_history(dialogueSession, workspace_id, '', result_msg,
                                                              query_time, id_result_json)
        send_data_by_redis(session_id, workspace_id, dialogueSession)
        dataHandling.create_dialogue_info(result["reply"], workspace_id, "IVR", session_id, 1,
                                          request_time=request_time, id_result_json=id_result_json,
                                          conversation_history=conversation_history)
        return result

    async def process(self, session_id, workspace_id, query, is_try, break_param):
        log.info('sessionId:{} query:{} break_param:{} is_try:{}'.format(session_id, query, break_param, is_try))
        query_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        request_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
        result = return_error()
        try:
            start_time = time.time()
            dialogueSession = dialogueStorage.get_dialogue_session(session_id, workspace_id)
            if dialogueSession is None or "accessDialogueId" not in dialogueSession:
                return result
            bot_name = dialogueSession.get("bot_name", '')
            llm_service_ip = dialogueSession.get("llm_service_ip", '')
            self.get_wechat_data(50, time.time(), start_time, '获取缓存', (time.time() - start_time) * 1000,
                                 session_id, bot_name, llm_service_ip)
            dialogue_id = dialogueSession.get("accessDialogueId")
            conversation_history = dialogueSession.get('conversation_history', list())

            # todo 后续将这块改为调用用户中心的redis 从而达到消息及时加载=======
            assistant_history_length = len(
                [message for message in conversation_history if message.get('role') == 'assistant'])
            if assistant_history_length == 1:
                user_info = get_case_info_by_session_id(session_id)
                base_info = dataHandling.data_handling_user_info(user_info, session_id)
                dialogueSession["baseInfo"] = base_info
                if user_info is not None:
                    dialogueSession["userInfo"] = user_info

                log.info('sessionId:{},重新获取了一次用户信息 获取结果:{}'.format(session_id, user_info))
            base_info = dialogueSession.get('baseInfo', '')
            # todo ============================

            conversation_history = dataHandling.data_handling_msg_data(conversation_history, query, constants.ROLE_USER,
                                                                       query_time)
            score = 0
            # 3.调用大模型
            start_time = time.time()
            llm_data = await self.get_llm_data(dialogue_id, conversation_history, session_id, base_info,
                                               dialogueSession.get('model_name'))
            self.get_wechat_data(1000, time.time(), start_time, '获取大模型结果', (time.time() - start_time) * 1000,
                                 session_id, bot_name, llm_service_ip)
            result_msg, id_result_json = dataHandling.data_handling_result(llm_data, base_info)
            result["reply"] = result_msg

            conversation_history = dataHandling.data_handling_msg_data(conversation_history, llm_data,
                                                                       constants.ROLE_ASSISTANT,
                                                                       datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
            dialogueSession["conversation_history"] = conversation_history
            if "true" in break_param:
                query = "{}{}".format("[#breakTrue#]", query)
            dialogueSession = dataHandling.update_session_history(dialogueSession, workspace_id, query, result_msg,
                                                                  query_time, id_result_json)
            llm_result = {"reply": result_msg}
            if "true" in break_param:
                llm_result["query"] = query

            dialogueStorage.set_dialogue_llm(session_id, workspace_id, llm_result)

            start_time = time.time()
            send_data_by_redis(session_id, workspace_id, dialogueSession)
            self.get_wechat_data(50, time.time(), start_time, '保存缓存', (time.time() - start_time) * 1000,
                                 session_id, bot_name, llm_service_ip)

            start_time = time.time()
            # 5.同步数据到ES
            dataHandling.create_dialogue_info(query, workspace_id, "USER", session_id,
                                              len(dialogueSession["dialogueHistory"][
                                                      "dialogueItemList"]) - 1,
                                              request_time=request_time, id_result_json=None,
                                              conversation_history=conversation_history)
            self.get_wechat_data(50, time.time(), start_time, '用户话术同步到ES', (time.time() - start_time) * 1000,
                                 session_id, bot_name, llm_service_ip)

            start_time = time.time()
            dataHandling.create_dialogue_info(result["reply"], workspace_id, "IVR", session_id,

                                              len(dialogueSession["dialogueHistory"][
                                                      "dialogueItemList"]),
                                              str(score), request_time=None,
                                              id_result_json=id_result_json,
                                              conversation_history=conversation_history)
            self.get_wechat_data(50, time.time(), start_time, '坐席话术同步到ES', (time.time() - start_time) * 1000,
                                 session_id, bot_name, llm_service_ip)
            if score is not None:
                result["reply"] = "{}{}".format(result["reply"], score)
        except Exception as e:
            log.error(e)
            traceback.print_exc()

        return result

    async def search_knowladge(self, dialogue_id, query, user_situation):

        credit_diff = global_dialogue_llm.get(dialogue_id)
        credit_in = credit_diff.get('class')(model_name='financial_loan_7b')

        knowledge_json = await credit_in.search_knowladge(query, user_situation)

        return knowledge_json

    def handleMissRecord(self, session_id, workspace_id, query):
        request_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
        result = "failure"
        # 1.从redis获取用户对话记录
        try:
            dialogue_info = dialogueStorage.get_dialogue_session(session_id, workspace_id)

            conversation_history = dialogue_info.get('conversation_history', list())
            conversation_history = dataHandling.data_handling_msg_data(conversation_history, query, constants.ROLE_USER,
                                                                       datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
            dialogue_info["conversation_history"] = conversation_history

            session_info = self.construct_session_information('', query, session_id, workspace_id, dialogue_info,
                                                              None)
            if session_info is not None:
                # 2.存入Redis中
                dialogueStorage.set_dialogue_session(session_id, workspace_id, dialogue_session=session_info)
                # 3.同步数据到ES
                user_content = dataHandling.create_dialogue_info(query, workspace_id, "USER", session_id,
                                                                 len(session_info["dialogueHistory"][
                                                                         "dialogueItemList"]),
                                                                 request_time=request_time, id_result_json=None,
                                                                 conversation_history=conversation_history)
                result = "success"
        except Exception as e:
            log.error("[handleMissRecord] 保存用户信息错误 error:{}".format(e))
        return result

    def end(self, session_id, workspace_id):
        # clearDialogueSession()
        pass

    def update_session_reply(self, reply, query, score, session):
        try:
            log.info("[update_session_reply] 修改session响应内容 session_id:{}".format(session["sessionId"]))
            dialogueList = session["dialogueHistory"]["dialogueItemList"]
            if reply is not None and len(dialogueList) > 0:
                dialogueList[len(dialogueList) - 1]["reply"] = reply
                dialogueList[len(dialogueList) - 1]["query"] = query
                dialogueList[len(dialogueList) - 1]["score"] = score
            if "processQueryResultStack" in session:
                dialogueList[len(dialogueList) - 1]["processQueryResultStack"] = session["processQueryResultStack"]
                del session["processQueryResultStack"]
        except Exception as e:
            log.error("[update_session_reply] 修改session响应内容 error:{}".format(e))

    def construct_session_information(self, reply: str, query: str, session_id, workspace_id, session,
                                      llm_data) -> dict:
        """
        构造对话数据，保存到旧Redis
        Args:
            reply (str): 机器人响应话术.
            query (str): 用户话术.
            session_id: session_id
            workspace_id: workspace_id
            session: session
        Returns:
            str: The greeting message.
            :param user_info:
        """
        log.info("[construct_session_information] reply:{}, query:{}".format(reply, query))
        if query is not None and "" != query and (reply is None or reply == ''):
            # 1.handle请求
            # 从redis获取用户对话记录
            dialogue_info = session
            if dialogue_info is not None and dialogue_info.get("processQueryResultStack") is None:
                handle_info = {
                    "query": query,
                    "queryTime": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                }
                dialogue_info["processQueryResultStack"] = {"processQueryLists": [handle_info]}
            elif dialogue_info is not None and dialogue_info.get("processQueryResultStack") is not None:
                handle_info = {
                    "query": query,
                    "queryTime": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                }
                dialogue_info["processQueryResultStack"]["processQueryLists"].append(handle_info)
            # session = dialogue_info
        elif query is not None and query != "" and reply is not None and reply != "":
            # 2.process请求
            # 从redis获取用户对话记录
            dialogue_info = session
            if dialogue_info is None or dialogue_info["dialogueHistory"]["dialogueItemList"] is None:
                return session
            history_len = len(dialogue_info["dialogueHistory"]["dialogueItemList"])
            dialogueItemList = dialogue_info["dialogueHistory"]["dialogueItemList"]
            if reply is not None and history_len > 0 and llm_data is not None:
                # dialogue_item = {
                #     "reply": reply,
                #     "workspaceId": workspace_id,
                #     "dialogueRound": history_len+1,
                #     "query": query,
                #     "replyTime": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                # }
                dialogue_item = llm_data
                dialogue_item["workspaceId"] = workspace_id
                dialogue_item["dialogueRound"] = history_len + 1
                dialogue_item["query"] = query
                dialogue_item["replyTime"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                if dialogue_info.get("processQueryResultStack") is not None:
                    dialogueItemList[history_len - 1]["processQueryResultStack"] = dialogue_info.get(
                        "processQueryResultStack")
                    del dialogue_info["processQueryResultStack"]
                else:
                    dialogue_info["processQueryResultStack"] = {
                        "processQueryLists": []
                    }
                dialogueItemList.append(dialogue_item)
        else:
            # 3.start请求
            session["dialogueHistory"] = {
                "dialogueItemList": [{
                    "reply": reply,
                    "workspaceId": workspace_id,
                    "dialogueRound": 1,
                    "replyTime": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                }]
            }
        return session

    def get_wechat_data(self, count, end_time, start_time, msg_name, time_data, session_id, bot_name, llm_service_ip):
        log.info('sessionId:{},获取{}时间:{}.'.format(session_id, msg_name, (end_time - start_time) * 1000))
        if ((end_time - start_time) * 1000) > count:
            msg = '{}响应时长:\n{}ms\nsessionId:{}\n机器人:{} \n报警服务器IP:{}'.format(msg_name, time_data,
                                                                                        session_id, bot_name,
                                                                                        llm_service_ip)
            response = threadpool.makeRequests(self.send_wechat_warning, [msg])
            pool.putRequest(response[0])

    def send_wechat_warning(self, msg):

        headers = {'Content-Type': 'application/json'}
        text = {'content': msg}
        webhook = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=a72dbd0e-d3bb-4e1a-a5e6-c0cd2cd9ce4c'
        data = {
            'msgtype': 'text',
            'text': text
        }
        data = json.dumps(data)
        response = requests.request('POST', webhook, headers=headers, data=data, timeout=1)

    async def get_llm_data(self, dialogue_id, conversation_history, session_id, base_info, model_name):
        credit_diff = global_dialogue_llm.get(dialogue_id)
        credit_in = credit_diff.get('class')(model_name=model_name)
        return await credit_in.async_reply(conversation_history, session_id, base_info)


# dialogService = dialogueService()

def get_dialog_service():
    dialogService = dialogueService()
    return dialogService


if __name__ == '__main__':

    pass
